home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_11_09 / 1109052a < prev    next >
Text File  |  1993-07-06  |  8KB  |  263 lines

  1. //  CStrWnd.cpp
  2.  
  3. //  See CStrWnd.h for a definition of what the
  4. //  class CStrWnd does
  5.  
  6. #include    "stdhdr.h"
  7. #include    "test_r.h"
  8. #include    "cstrwnd.h"
  9. #include    "strdetab.h"
  10.  
  11. CStrWnd::CStrWnd (const char * window_name)
  12. {
  13. VERIFY (LoadAccelTable ("CStrWndAccelTable"));
  14. VERIFY (Create (NULL, window_name,
  15.                 WS_CHILD | WS_VSCROLL, rectDefault,
  16.                 NULL));
  17. SetFocus ();
  18. current_first_row = 0; current_first_col = 0;
  19. h_scroll_flag = 0;
  20. length_of_longest_line = 0;
  21. }
  22.  
  23. BEGIN_MESSAGE_MAP (CStrWnd, CMDIChildWnd)
  24.     ON_WM_PAINT ()
  25.     ON_WM_VSCROLL ()
  26.     ON_WM_HSCROLL ()
  27.     ON_WM_KEYDOWN ()
  28.  
  29.     ON_COMMAND (CSW_DOC_START, OnDocStart)
  30.     ON_COMMAND (CSW_DOC_END, OnDocEnd)
  31.     ON_COMMAND (CSW_LINE_RIGHT, OnLineRight)
  32.     ON_COMMAND (CSW_LINE_LEFT, OnLineLeft)
  33. END_MESSAGE_MAP ()
  34.  
  35. afx_msg void CStrWnd::OnPaint ()
  36. {
  37. CPaintDC dc (this);
  38. //  Use a fixed-pitch font for better presentation
  39. VERIFY (dc.SelectStockObject(OEM_FIXED_FONT) != NULL);
  40.  
  41. //  First find out number of lines in the window
  42. TEXTMETRIC tm;
  43. VERIFY (dc.GetTextMetrics (&tm));
  44. const int char_height = tm.tmHeight
  45.                         + tm.tmExternalLeading;
  46. const int char_width = tm.tmAveCharWidth;
  47. CRect rect;
  48. GetClientRect (rect);
  49. no_of_lines = rect.Height () / char_height;
  50. no_of_chars_in_line = rect.Width () / char_width;
  51.  
  52. //  Set up the tab stop positions
  53. const int tab_interval = 4;
  54. const int no_of_tabs = 120 / tab_interval;
  55. int char_tab_stops [no_of_tabs];
  56. for (int i = 0; i < no_of_tabs; i++)
  57.     char_tab_stops [i] = (i + 1) * tab_interval;
  58.  
  59. //  Write a window_full of text
  60.  
  61. for (int lc = 0;
  62.      lc < no_of_lines
  63.      && current_first_row + lc
  64.         < text_buffer.GetSize ();
  65.      lc++)
  66.     {
  67.     const int max_line_length = 256;
  68.     char out_buf [max_line_length + 1];
  69.     int line_length;
  70.     //  Convert tabs to spaces
  71.     strdetab (out_buf, max_line_length,
  72.               text_buffer [current_first_row + lc],
  73.               no_of_tabs, char_tab_stops,
  74.               &line_length);
  75.     //  Get pointer to first char in line for output
  76.     const char * first_char = out_buf
  77.                               + current_first_col;
  78.     //  Update record of longest line length
  79.     if (length_of_longest_line < line_length)
  80.         length_of_longest_line = line_length;
  81.     //  Call up horizontal scroll bar if needed
  82.     if (line_length > no_of_chars_in_line)
  83.         h_scroll_flag = 1;
  84.     dc.TextOut (0, lc * char_height, first_char,
  85.                 line_length - current_first_col);
  86.     }
  87. if (h_scroll_flag) ShowScrollBar (SB_HORZ, TRUE);
  88. }
  89.  
  90. afx_msg void CStrWnd::OnVScroll (UINT nSBCode,
  91.                                  UINT npos,
  92.                                  CScrollBar * pBar)
  93. {
  94. int min_scroll_pos, max_scroll_pos,
  95.     max_index = text_buffer.GetSize () - 1,
  96.     scrolled = 1;
  97. if (max_index < 0) max_index = 0;
  98.     //  Cater for no lines in text_buffer
  99. switch (nSBCode)
  100.     {
  101.     case SB_LINEDOWN:
  102.         current_first_row++; break;
  103.     case SB_PAGEDOWN:
  104.         current_first_row += no_of_lines - 1; break;
  105.     case SB_LINEUP:
  106.         current_first_row--; break;
  107.     case SB_PAGEUP:
  108.         current_first_row -= no_of_lines - 1; break;
  109.     case SB_THUMBPOSITION:
  110.         GetScrollRange (SB_VERT, &min_scroll_pos,
  111.                         &max_scroll_pos);
  112.         current_first_row =
  113.             (max_index * (npos - min_scroll_pos))
  114.              / (max_scroll_pos - min_scroll_pos);
  115.         break;
  116.     default:
  117.     //  We did nothing, so do not update the window!
  118.         scrolled = 0; break;
  119.     }
  120.  
  121. if (scrolled)
  122.     {
  123.     //  Now make sure that the current row is in range
  124.     if (current_first_row < 0) current_first_row = 0;
  125.     if (current_first_row > max_index)
  126.         current_first_row = max_index;
  127.     Invalidate (TRUE);
  128.     SetVerticalScroll ();
  129.     UpdateWindow ();
  130.     }
  131. }
  132.  
  133. afx_msg void CStrWnd::OnHScroll (UINT nSBCode,
  134.                                  UINT npos,
  135.                                  CScrollBar * pBar)
  136. {
  137. int min_scroll_pos, max_scroll_pos,
  138.     scrolled = 1;
  139. GetScrollRange (SB_VERT, &min_scroll_pos,
  140.                 &max_scroll_pos);
  141. switch (nSBCode)
  142.     {
  143.     case SB_LINERIGHT:
  144.         current_first_col++; break;
  145.     case SB_PAGERIGHT:
  146.         current_first_col += 10; break;
  147.     case SB_LINELEFT:
  148.         current_first_col--; break;
  149.     case SB_PAGELEFT:
  150.         current_first_col -= 10; break;
  151.     case SB_LEFT:
  152.         current_first_col = 0; break;
  153.     case SB_RIGHT:
  154.         current_first_col = length_of_longest_line - 1;
  155.         break;
  156.     case SB_THUMBPOSITION:
  157.         current_first_col =
  158.             ((length_of_longest_line - 1)
  159.              * (npos - min_scroll_pos))
  160.              / (max_scroll_pos - min_scroll_pos);
  161.         break;
  162.     default:
  163.         //  We did nothing, so do not update  window!
  164.         scrolled = 0; break;
  165.     }
  166.  
  167. if (scrolled)
  168.     {
  169.     //  Now ensure that we are within limits
  170.     if (current_first_col < 0) current_first_col = 0;
  171.     if (current_first_col >= length_of_longest_line)
  172.         current_first_col = length_of_longest_line - 1;
  173.     Invalidate (TRUE);
  174.     if (h_scroll_flag)
  175.         SetScrollPos (SB_HORZ,
  176.                   ((max_scroll_pos - min_scroll_pos)
  177.                   * current_first_col)
  178.                   / (length_of_longest_line -1)
  179.                   + min_scroll_pos,
  180.                   TRUE);
  181.     UpdateWindow ();
  182.     }
  183. }
  184.  
  185. afx_msg void CStrWnd::OnKeyDown (UINT nChar,
  186.                                  UINT nRepCnt,
  187.                                  UINT nFlags)
  188. {
  189. switch (nChar)
  190.     {
  191.     case VK_DOWN:
  192.         OnVScroll (SB_LINEDOWN, 0, NULL); break;
  193.     case VK_NEXT:                   // Page down
  194.         OnVScroll (SB_PAGEDOWN, 0, NULL); break;
  195.     case VK_UP:
  196.         OnVScroll (SB_LINEUP, 0, NULL); break;
  197.     case VK_PRIOR:                  // Page up
  198.         OnVScroll (SB_PAGEUP, 0, NULL); break;
  199.     case VK_LEFT:
  200.         OnHScroll (SB_LINELEFT, 0, NULL); break;
  201.     case VK_HOME:
  202.         OnHScroll (SB_LEFT, 0, NULL); break;
  203.     case VK_RIGHT:
  204.         OnHScroll (SB_LINERIGHT, 0, NULL); break;
  205.     case VK_END:
  206.         OnHScroll (SB_RIGHT, 0, NULL); break;
  207.     }
  208. }
  209.  
  210. afx_msg void CStrWnd::OnDocStart ()
  211. {
  212. int min_scroll_pos, max_scroll_pos;
  213. GetScrollRange (SB_VERT, &min_scroll_pos,
  214.                 &max_scroll_pos);
  215. Invalidate (TRUE);
  216. current_first_row = 0;
  217. SetScrollPos (SB_VERT, min_scroll_pos, TRUE);
  218. UpdateWindow ();
  219. }
  220.  
  221. afx_msg void CStrWnd::OnDocEnd ()
  222. {
  223. int min_scroll_pos, max_scroll_pos;
  224. GetScrollRange (SB_VERT, &min_scroll_pos,
  225.                 &max_scroll_pos);
  226. Invalidate (TRUE);
  227. current_first_row = text_buffer.GetUpperBound () - 4;
  228. //  Leave 4 lines on the screen
  229. if (current_first_row < 0) current_first_row = 0;
  230. SetScrollPos (SB_VERT, max_scroll_pos, TRUE);
  231. UpdateWindow ();
  232. }
  233.  
  234. afx_msg void CStrWnd::OnLineRight ()
  235. {OnHScroll (SB_PAGERIGHT, 0, NULL);}
  236.  
  237. afx_msg void CStrWnd::OnLineLeft ()
  238. {OnHScroll (SB_PAGELEFT, 0, NULL);}
  239.  
  240. void CStrWnd::UpdateScreen ()
  241. {
  242. current_first_row = text_buffer.GetUpperBound ()
  243.                     - no_of_lines;
  244. if (current_first_row < 0) current_first_row = 0;
  245. SetVerticalScroll ();
  246. Invalidate (TRUE);
  247. UpdateWindow ();
  248. }
  249.  
  250. void CStrWnd::SetVerticalScroll ()
  251. {
  252. int min_scroll_pos, max_scroll_pos,
  253.     max_index = text_buffer.GetUpperBound ();
  254. GetScrollRange (SB_VERT, &min_scroll_pos,
  255.                 &max_scroll_pos);
  256. SetScrollPos (SB_VERT,
  257.               ((max_scroll_pos - min_scroll_pos )
  258.                 * current_first_row)
  259.               / ((max_index > 0) ? max_index : 1)
  260.               + min_scroll_pos,
  261.               TRUE);
  262. }
  263.